package com.mapfinal.data.postgis;

import java.util.List;
import java.util.Map;

import com.beust.jcommander.internal.Lists;
import com.google.common.collect.Maps;
import com.jfinal.config.Plugins;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.IPlugin;
import com.jfinal.plugin.activerecord.DbKit;
import com.lambkit.common.util.EncryptUtils;
import com.lambkit.db.DbManager;
import com.lambkit.db.datasource.DataSourceConfig;
import com.lambkit.db.meta.MetaKit;
import com.lambkit.db.meta.TableMeta;
import com.mapfinal.data.MapLayer;
import com.mapfinal.data.MapStore;
import com.mapfinal.data.StoreManager;
import com.mapfinal.data.StoreType;

public class PostgisStore implements MapStore {

	private String name;
	private List<MapLayer> layers;
	private List<String> datas;
	
	private DataSourceConfig config;
	private String host;
	private int port;
	private String dbname;

	public static PostgisStore create(DataSourceConfig config, Boolean started) {
		if (config == null)
			return null;
		if (!config.isConfigOk()) {
			return null;
		}
		PostgisStore store = new PostgisStore();
		store.setConfig(config);
		String url = config.getUrl();
		url = url.replace("jdbc:postgresql://", "");
		int i = url.indexOf(":");
		int j = url.indexOf("/");
		store.setHost(url.substring(0, i));
		store.setPort(Integer.valueOf(url.substring(i + 1, j)));
		store.setDbname(url.substring(j + 1));
		String name = config.getName();
		if(StrKit.isBlank(name)) {
			name = store.getDbname();
		}
		if(StrKit.isBlank(name) || StoreManager.me().getStore(name)!=null) {
			return null;
		}
		store.setName(name);
		if(started!=null && started==false) {
			Plugins plugins = new Plugins();
			if(DbManager.me().getDbWrapper(store.getConfigName())==null) {
				DbManager.me().addArp(plugins, config);
			}
			for (IPlugin plugin : plugins.getPluginList()) {
				plugin.start();
			}
		}
		// 遍历数据库表格，加入datas
		Map<String, Object> options = Maps.newHashMap();
		//不包含如下数据表
		options.put("excludedTables", "sys_fieldconfig, sys_tableconfig, pointcloud_formats, spatial_ref_sys");
		Map<String, TableMeta> tables = MetaKit.getTableMetas(DbKit.getConfig(config.getName()), options);
		for (TableMeta table : tables.values()) {
			store.addData(table.getName());
			PostgisLayer layer = new PostgisLayer();
			layer.setName(table.getAttrName());
			layer.setTitle(table.getTitle());
			layer.setNativeName(table.getName());
			layer.setStoreName(name);
			if (StrKit.notBlank(layer.getName()) && StrKit.notBlank(layer.getNativeName())
					&& StrKit.notBlank(layer.getStoreName())) {
				store.publish(layer.getNativeName(), layer);
			}
		}
		StoreManager.me().addStore(store);
		return store;
	}
	
	public String getConfigName() {
		if(StrKit.isBlank(config.getName())) {
			String name = host + port + dbname;
			config.setName(EncryptUtils.md5(name));
		}
		return config.getName();
	}

	/**
	 * 发布
	 * @param name
	 * @param server
	 */
	@Override
	public void publish(String dataName, MapLayer layer) {
		datas.remove(name);
		addLayer(layer);
	}
	
	@Override
	public StoreType getType() {
		// TODO Auto-generated method stub
		return StoreType.POSTGIS;
	}

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return name;
	}

	@Override
	public void addLayer(MapLayer layer) {
		// TODO Auto-generated method stub
		if(layers==null) {
			layers = Lists.newArrayList();
		}
		layers.add(layer);
	}
	
	@Override
	public MapLayer getLayer(String name) {
		// TODO Auto-generated method stub
		if(layers!=null) {
			for (MapLayer layer : layers) {
				if(layer.getName().equalsIgnoreCase(name)) {
					return layer;
				}
			}
		}
		return null;
	}

	@Override
	public List<MapLayer> getLayers() {
		// TODO Auto-generated method stub
		return layers;
	}
	
	public void addData(String tableName) {
		if(datas==null) {
			datas = Lists.newArrayList();
		}
		datas.add(tableName);
	}
	@Override
	public List<String> getDatas() {
		// TODO Auto-generated method stub
		return datas;
	}
	
	public void setLayers(List<MapLayer> layers) {
		this.layers = layers;
	}

	public void setName(String name) {
		this.name = name;
	}

	public DataSourceConfig getConfig() {
		return config;
	}

	public void setConfig(DataSourceConfig config) {
		this.config = config;
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public String getDbname() {
		return dbname;
	}

	public void setDbname(String dbname) {
		this.dbname = dbname;
	}

	public void setDatas(List<String> datas) {
		this.datas = datas;
	}

	@Override
	public Map<String, Object> info() {
		// TODO Auto-generated method stub
		Map<String, Object> info = Maps.newHashMap();
		info.put("name", name);
		info.put("host", host);
		info.put("port", port);
		info.put("dbname", dbname);
		info.put("type", config.getType());
		info.put("schema", config.getSchema());
		info.put("config", config.getName());
		return info;
	}
}
